/*
 * @Author: yuki
 * @Date: 2025-11-04 21:17:37
 * @LastEditTime: 2025-11-06 19:49:37
 * @Description: 登录弹窗
 */
import { PASSWORD_REG, EMAIL_REG, IP_DOMAIN_REG } from '@horoscope/shared';
import { useSpring, animated } from '@react-spring/web';
import { useDebounceFn } from 'ahooks';
import { Modal, Form, Input, Button, message } from 'antd';
import classNames from 'classnames';
import type {
  FieldData,
  ValidateErrorEntity
} from 'rc-field-form/lib/interface';
import { memo, useState } from 'react';
import type { FC, ReactNode } from 'react';

import loginImg from '@/assets/image/login.png';
import registerImg from '@/assets/image/register.png';
import { register } from '@/request';
import {
  useModuleSelector,
  useAppDispatch,
  setShowLoginModal,
  fetchLogin
} from '@/store/index';

import style from './LoginModal.module.scss';

interface IProps {
  children?: ReactNode;
}

interface IFormValues {
  username: string;
  email: string;
  password: string;
  confirmPassword: string;
}

const LoginModal: FC<IProps> = () => {
  const showLoginModal = useModuleSelector(
    'user',
    state => state.showLoginModal
  );

  const dispatch = useAppDispatch();

  const [isLogin, setIsLogin] = useState(false);
  const [loading, setLoading] = useState(false);
  const [isAnimate, setIsAnimate] = useState(false);

  const [formIns] = Form.useForm();

  const { x } = useSpring({
    from: { x: 0 },
    to: { x: isAnimate ? 1 : 0 },
    config: { duration: 1000 },
    reset: true, // 每次动画都从初始状态开始
    onRest: () => {
      // 动画完成后重置状态，确保下次点击可以正常触发动画
      if (isAnimate) {
        setIsAnimate(false);
      }
    }
  });

  const handleClose = () => {
    dispatch(setShowLoginModal(false));
  };

  const { run: handleSubmit } = useDebounceFn(
    () => {
      formIns.submit();
    },
    {
      wait: 500,
      leading: true
    }
  );

  const handleChangeLoginType = (type: boolean) => {
    formIns.resetFields();
    setIsLogin(type);
  };

  const handleFieldsChange = (changedFields: FieldData<IFormValues>[]) => {
    changedFields.forEach(filed => {
      const { name } = filed;
      formIns.setFieldValue(
        name[0],
        ((filed.value as string) || '').replace(/\s/g, '')
      );
    });
  };

  const handleFinishFailed = (errorInfo: ValidateErrorEntity<IFormValues>) => {
    const errMsg = errorInfo.errorFields
      .map(field => field.errors[0])
      .join(',');
    message.error(errMsg);
    setIsAnimate(true);
  };

  const handleLogin = async (values: IFormValues) => {
    const res = await dispatch(fetchLogin(values));
    if (fetchLogin.rejected.match(res)) {
      message.error(res.payload as string);
      throw new Error(res.payload as string);
    } else {
      message.success('登陆成功');
      dispatch(setShowLoginModal(false));
    }
  };

  const handleRegister = async (values: IFormValues) => {
    try {
      const res = await register(values);
      if (res.success) {
        setIsLogin(true);
      } else {
        message.error(res.message);
      }
    } catch (err) {
      message.error((err as Error).message);
    }
  };

  const handleFinish = async (values: IFormValues) => {
    setLoading(true);
    try {
      if (isLogin) {
        await handleLogin(values);
      } else {
        await handleRegister(values);
      }
    } finally {
      setLoading(false);
    }
  };

  return (
    <Modal
      open={showLoginModal}
      onCancel={handleClose}
      footer={null}
      className={classNames(style['login-modal'])}
      width={700}
      centered
    >
      <div className='login-modal-container'>
        <Form
          form={formIns}
          className={classNames('login-modal-container_form', {
            'translate-x-full': !isLogin
          })}
          onFinish={handleFinish}
          onFinishFailed={handleFinishFailed}
          onFieldsChange={handleFieldsChange}
          validateTrigger={['submit']}
        >
          <h1 className='text-center text-[24px] font-bold text-white mb-6'>
            {isLogin ? '登录' : '注册'}
          </h1>
          <Form.Item
            help=''
            name='username'
            rules={[
              {
                validator: (_, value: string) => {
                  if (!value) {
                    return Promise.reject(new Error('必须提供用户名或邮箱'));
                  }
                  // 如果提供了用户名，必须是4-16个字符
                  const trimmedValue = value.replace(/\s/g, '');
                  if (trimmedValue.length < 4 || trimmedValue.length > 16) {
                    return Promise.reject(
                      new Error('用户名长度必须是4到16个字符')
                    );
                  }
                  return Promise.resolve();
                }
              }
            ]}
          >
            <Input
              maxLength={16}
              placeholder={!isLogin ? '用户名（4-16个字符）' : '用户名/邮箱'}
            />
          </Form.Item>
          {!isLogin && (
            <Form.Item
              help=''
              name='email'
              rules={[
                {
                  validator: (_, value: string) => {
                    // 注册时邮箱可选，但如果提供了必须验证格式
                    if (!value) {
                      return Promise.resolve();
                    }
                    // 邮箱格式验证（不允许 IP 域名，允许下划线）
                    if (!EMAIL_REG.test(value)) {
                      return Promise.reject(new Error('邮箱格式错误'));
                    }
                    // 不允许 IP 域名
                    if (IP_DOMAIN_REG.test(value)) {
                      return Promise.reject(new Error('邮箱格式错误'));
                    }
                    return Promise.resolve();
                  }
                }
              ]}
            >
              <Input placeholder='邮箱' />
            </Form.Item>
          )}
          <Form.Item
            help=''
            name='password'
            rules={[
              {
                required: true,
                message: '密码不能为空'
              },
              {
                validator: (_, value: string) => {
                  if (!value) {
                    return Promise.resolve();
                  }
                  if (!PASSWORD_REG.test(value)) {
                    return Promise.reject(
                      new Error(
                        '密码必须包含数字和英文字母，可包含!@#$%^&*等特殊字符（长度8-20位）'
                      )
                    );
                  }
                  return Promise.resolve();
                }
              }
            ]}
          >
            <Input.Password
              maxLength={20}
              placeholder='密码（8-20位，包含数字和英文字母）'
            />
          </Form.Item>
          {!isLogin && (
            <Form.Item
              help=''
              name='confirmPassword'
              dependencies={['password']}
              rules={[
                {
                  required: true,
                  message: '确认密码不能为空'
                },
                ({ getFieldValue }) => ({
                  validator: (_, value: string) => {
                    if (!value) {
                      return Promise.resolve();
                    }
                    if (!PASSWORD_REG.test(value)) {
                      return Promise.reject(
                        new Error(
                          '密码必须包含数字和英文字母，可包含!@#$%^&*等特殊字符（长度8-20位）'
                        )
                      );
                    }
                    if (getFieldValue('password') !== value) {
                      return Promise.reject(new Error('两次输入的密码不一致'));
                    }
                    return Promise.resolve();
                  }
                })
              ]}
            >
              <Input.Password
                maxLength={20}
                placeholder='确认密码需和密码一致'
              />
            </Form.Item>
          )}
          <animated.div
            className='w-full flex justify-center'
            style={{
              // 初始和结束状态都是完全可见（opacity = 1），动画过程中有轻微变化
              opacity: x.to({ range: [0, 1], output: [1, 1] }),
              scale: x.to({
                range: [0, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 1],
                output: [1, 0.97, 0.9, 1.1, 0.9, 1.1, 1.03, 1]
              })
            }}
          >
            <Button
              loading={loading}
              onClick={() => handleSubmit()}
              className='form_btn'
            >
              {isLogin ? '登录' : '注册'}
            </Button>
          </animated.div>
        </Form>
        <div className='login-modal-container_wrap'>
          <h2 className='wrap_title'>
            欢迎来到<span className='wrap_title_highlight'>赛博占卜</span>
          </h2>
          <p className='wrap_desc'>
            快来占卜你的<span className='wrap_title_highlight'>命运</span>吧
          </p>
          <img
            className='wrap_img'
            src={registerImg}
            alt=''
          />
          <p className='wrap_desc'>已有账号</p>
          <Button
            onClick={() => {
              handleChangeLoginType(true);
            }}
            className='wrap_btn'
          >
            去登录
          </Button>
        </div>
        <div className='login-modal-container_wrap'>
          <h2 className='wrap_title'>
            欢迎来到<span className='wrap_title_highlight'>赛博占卜</span>
          </h2>
          <p className='wrap_desc'>
            快来占卜你的<span className='wrap_title_highlight'>命运</span>吧
          </p>
          <img
            className='wrap_img'
            src={loginImg}
            alt=''
          />
          <p className='wrap_desc'>已有账号</p>
          <Button
            onClick={() => {
              handleChangeLoginType(false);
            }}
            className='wrap_btn'
          >
            去注册
          </Button>
        </div>
      </div>
    </Modal>
  );
};

export default memo(LoginModal);
